﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ServiceModel;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Globalization;

namespace VAdvantageSvc
{
    [DataContract]
    public class CustomException
    {

        [DataMember(Order = 0)]
        public string Message { get; set; }
        [DataMember(Order = 1)]
        public CustomException InnerException;

        public CustomException(Exception ex)
        {
            while (ex.InnerException != null)
                ex = ex.InnerException;
            this.Message = ex.Message + ex.StackTrace;
        }
        public Exception ToException()
        {
            Exception e;
            CustomException ce = this;
            if (ce.InnerException != null)
            {
                Exception inner = ce.InnerException.ToException();
                e = new Exception(ce.Message, inner);
            }
            else
                e = new Exception(ce.Message);
            return e;
        }


    }

    [DataContract]
    public class DataColumnInfo
    {
        [DataMember]
        public string ColumnName { get; set; }

        [DataMember]
        public string ColumnTitle { get; set; }

        [DataMember]
        public string DataTypeName { get; set; }

        [DataMember]
        public bool IsRequired { get; set; }

        [DataMember]
        public bool IsKey { get; set; }

        [DataMember]
        public bool IsReadOnly { get; set; }

        [DataMember]
        public int DisplayIndex { get; set; }

        [DataMember]
        public string EditControlType { get; set; }

        [DataMember]
        public int MaxLength { get; set; }
    }

    /// <summary>
    /// Summary description for DataTableInfo
    /// </summary>
    [DataContract]
    public class DataTableInfo
    {
        [DataMember]
        public string TableName { get; set; }

        [DataMember]
        public ObservableCollection<DataColumnInfo> Columns { get; set; }

    }

    [DataContract]
    public class DataSetData
    {
        [DataMember]
        public ObservableCollection<DataTableInfo> Tables { get; set; }
        [DataMember]
        public string DataXML { get; set; }

        public static DataSetData FromDataSet(DataSet ds)
        {
            DataSetData dsd = new DataSetData();
            dsd.Tables = new ObservableCollection<DataTableInfo>();
            foreach (DataTable t in ds.Tables)
            {
                DataTableInfo tableInfo = new DataTableInfo { TableName = t.TableName };
                dsd.Tables.Add(tableInfo);
                tableInfo.Columns = new ObservableCollection<DataColumnInfo>();
                foreach (DataColumn c in t.Columns)
                {
                    DataColumnInfo col = new DataColumnInfo { ColumnName = c.ColumnName, ColumnTitle = c.ColumnName, DataTypeName = c.DataType.FullName, MaxLength = c.MaxLength, IsKey = c.Unique, IsReadOnly = (c.Unique || c.ReadOnly), IsRequired = !c.AllowDBNull };
                    if (c.DataType == typeof(System.Guid))
                    {
                        col.IsReadOnly = true;
                        col.DisplayIndex = -1;
                    }
                    tableInfo.Columns.Add(col);
                }
            }

            ds = Util.SetUtcDateTime(ds);

            dsd.DataXML = ds.GetXml();
            return dsd;
        }

        public static DataSet ToDataSet(DataSetData dsd)
        {
            DataSet ds = new DataSet();
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(dsd.DataXML);
            MemoryStream stream = new MemoryStream(byteArray);
            XmlReader reader = new XmlTextReader(stream);
            ds.ReadXml(reader);
            XDocument xd = XDocument.Parse(dsd.DataXML);
            foreach (DataTable dt in ds.Tables)
            {
                var rs = from row in xd.Descendants(dt.TableName)
                         select row;

                int i = 0;
                foreach (var r in rs)
                {
                    DataRowState state = (DataRowState)Enum.Parse(typeof(DataRowState), r.Attribute("RowState").Value);
                    DataRow dr = dt.Rows[i];
                    dr.AcceptChanges();
                    if (state == DataRowState.Deleted)
                        dr.Delete();
                    else if (state == DataRowState.Added)
                        dr.SetAdded();
                    else if (state == DataRowState.Modified)
                        dr.SetModified();
                    i++;
                }
            }
            return ds;
        }
    }

    [DataContract] 
    public class SqlParameter
    {
        private object _value;
        private String _name;

        [DataMember]
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
        
        [DataMember]
        public object Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
            }
        }

        public SqlParameter(string name,object value)
        {
            Name = name;
            Value = value;
        }
    }

    public class Util
    {
        public static DataSet SetUtcDateTime(DataSet dataSet)
        {
            var ds = new DataSet { Locale = CultureInfo.InvariantCulture };
            foreach (DataTable source in dataSet.Tables)
            {
                bool containsDate = false;
                var target = source.Clone();

                foreach (DataColumn col in target.Columns)
                {
                    if (col.DataType == System.Type.GetType("System.DateTime"))
                    {
                        col.DateTimeMode = DataSetDateTime.Utc;
                        containsDate = true;
                    }
                }

                if (containsDate)
                {
                    foreach (DataRow row in source.Rows)
                        target.ImportRow(row);
                    ds.Tables.Add(target);
                }
                else
                {
                    ds.Tables.Add(source.Copy());
                }
            }
            dataSet.Tables.Clear();
            dataSet = ds;
            return dataSet;
        }

        public static DataTable SetUtcDateTime(DataTable source)
        {
            //var ds = new DataSet { Locale = CultureInfo.InvariantCulture };

            var target = source.Clone();

            //foreach (DataTable source in dataSet.Tables)
            //{
                bool containsDate = false;
            //    var target = source.Clone();

                foreach (DataColumn col in target.Columns)
                {
                    if (col.DataType == System.Type.GetType("System.DateTime"))
                    {
                        col.DateTimeMode = DataSetDateTime.Utc;
                        containsDate = true;
                    }
                }

                if (containsDate)
                {
                    foreach (DataRow row in source.Rows)
                        target.ImportRow(row);
                    return target;
                    //ds.Tables.Add(target);
                }
                //else
                //{
                //    ds.Tables.Add(source.Copy());
                //}
            //}

                return source;
        }
    }
}
